#include "aerial\vulcan.h"
#include "hge\hgecolor.h"

#include "aerial\Fighter.h"

const float Vulcan::Speed = 1000.f;
const float Vulcan::BSpeed = 22.f;
const float Vulcan::MinPowerRequire = 0.f;
const float Vulcan::PCPS = 0.f;
const int Vulcan::FadeSpeed = 1;
const float Vulcan::MaxRange = 600.f;

bool Vulcan::available(FlyObject* fo)	{	return fo->GetPower() > MinPowerRequire; }

Vulcan::Vulcan(float sx, float sy, float vx, float vy, FlyObject* host)
	: Weapon(sx, sy, vx, vy, host), max_range(MaxRange), vulcanState(Expanding)
{
	VRCC = new VulcanRayCastCallback(this);
	
	t_range = 0.f;
	powerConsume = 100;

	destPoint = BattleHelper::getBox2dCoordinateFromHge(
		b2Vec2(T.x + D.x * MaxRange, T.y + D.y * MaxRange)
		);

	psInner = new hgeParticleSystem(&hgeResMan->GetParticleSystem("ps.vulcan.inner")->info);
	psInner->info.fSizeStart = 2.0;
	psInner->info.colColorStart.r = 1.0;
	psInner->info.colColorStart.g = 1.0;
	psInner->info.colColorStart.b = 1.0;
	
	psInner->info.colColorEnd.r = 1.0;
	psInner->info.colColorEnd.g = 1.0;
	psInner->info.colColorEnd.b = 1.0;

	psInner->info.nEmission = 100;
	psInner->info.fParticleLifeMin = 2.3f;

	psOuter = new hgeParticleSystem(&hgeResMan->GetParticleSystem("ps.vulcan.outer")->info);
	psOuter->info.colColorStart.r = 0;
	psOuter->info.colColorStart.g = 0;
	psOuter->info.colColorStart.b = 1.0;
	
	psOuter->info.colColorEnd.r = 0;
	psOuter->info.colColorEnd.g = 0;
	psOuter->info.colColorEnd.b = 1.0;

	psOuter->info.nEmission = 100;
	psOuter->info.fParticleLifeMin = 2.3f;

	psInner->FireAt(T.x, T.y);
	psOuter->FireAt(T.x, T.y);
}

void Vulcan::render()
{
	psOuter->Render();
	psInner->Render();
}

bool Vulcan::update(float dt)
{
	if (vulcanState == Expanding || vulcanState == Full)
	{
		if (host->UsePower(dt * PCPS)) {
			stop();
		}
		b2Vec2 S = BattleHelper::getBox2dCoordinateFromHge(T);
		world->RayCast(VRCC, S, destPoint);
	}
	else {
		psInner->info.nEmission -= FadeSpeed;
		psOuter->info.nEmission -= FadeSpeed;

		if (psInner->info.nEmission <= 0) {
#ifdef _DEBUG
			assert(host);	
#endif
			psInner->info.nEmission = 0;
			psOuter->info.nEmission = 0;
			return true;
		}
	}

	t_range += Speed * dt;
	if (t_range > max_range) t_range = 0.f;

	psInner->MoveTo(T.x + D.x * t_range, T.y + D.y * t_range);
	psOuter->MoveTo(T.x + D.x * t_range, T.y + D.y * t_range);
	psOuter->Update(dt);
	psInner->Update(dt);
	return false;
}

void Vulcan::Hit(float fraction)
{
	max_range = MaxRange * fraction;
}

void Vulcan::stop()
{
	vulcanState = Fade;
#ifdef _DEBUG
	assert(host);
#endif
	((Fighter*)host)->SetState(0, F_V_VULCAN);
	((Fighter*)host)->DisableVulcan();
}

bool Vulcan::isOn()
{
	return vulcanState == Expanding || vulcanState == Full;
}

Vulcan::~Vulcan()
{
	delete psInner;
	delete psOuter;
}

float32 VulcanRayCastCallback::ReportFixture(b2Fixture *fixture,  const b2Vec2& point,  const b2Vec2& normal, float32 fraction)
{
	m_fixture = fixture;
	m_point = point;
	m_normal = normal;
	m_fraction = fraction;
	GameObject* gObj = (GameObject*)fixture->GetBody()->GetUserData();
	if (gObj->GetObjectType() == TYPE_FLY)
	{
		if ((FlyObject*)gObj == vulcan->GetHost()) return 0;
		else {
			vulcan->Hit(fraction);
			((FlyObject*)gObj)->TakeEffect(vulcan);
			//dosomething
			return fraction;
		}
	} else {
		Weapon* weapon = (Weapon*)gObj;
		if (weapon->GetWeaponType() == TYPE_WEAPON_VULCAN) return 0;
		else {
			//dosomething
			return fraction;
		}
	}
}